package com.ruoyi.project.fusion.algorithms;

import com.ruoyi.project.fusion.domain.TechnologyAggInfo;
import com.ruoyi.project.fusion.domain.TechnologyScores;
import com.ruoyi.project.fusion.utils.ComputeUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TechnologyAlgorithm {
    public List<TechnologyScores> compute(List<TechnologyAggInfo> technologyAggInfos) {
        List<TechnologyScores> scoresList = new ArrayList<>();

        // 按照 chainType、scenario、product 分组
        Map<List<String>, List<TechnologyAggInfo>> groupedInfos = technologyAggInfos.stream()
                .collect(Collectors.groupingBy(info -> Arrays.asList(
                        info.getChainType(),
                        info.getScenario(),
                        info.getProduct(),
                        info.getEvent()
                )));

        for (Map.Entry<List<String>, List<TechnologyAggInfo>> entry : groupedInfos.entrySet()) {
            List<TechnologyAggInfo> group = entry.getValue();

            // 归一化数据
            List<Double> normalizedAverageProductionCycle = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgAverageProductionCycle).collect(Collectors.toList()));
            List<Double> normalizedQualityCheckPassRate = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgQualityCheckPassRate).collect(Collectors.toList()));
            List<Double> normalizedEquipmentAutomationLevel = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgEquipmentAutomationLevel).collect(Collectors.toList()));
            List<Double> normalizedMonthlyCapacity = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgMonthlyCapacity).collect(Collectors.toList()));
            List<Double> normalizedMaxCapacity = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgMaxCapacity).collect(Collectors.toList()));
            List<Double> normalizedEquipmentFailureRate = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgEquipmentFailureRate).collect(Collectors.toList()));
            List<Double> normalizedQualityCertificateCount = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgQualityCertificateCount).collect(Collectors.toList()));
            List<Double> normalizedPatentCount = ComputeUtils.normalizeValues(group.stream().map(TechnologyAggInfo::getAvgPatentCount).collect(Collectors.toList()));

            // 计算各项指标的标准差
            double stdDevAverageProductionCycle = ComputeUtils.calculateStandardDeviation(normalizedAverageProductionCycle);
            double stdDevQualityCheckPassRate = ComputeUtils.calculateStandardDeviation(normalizedQualityCheckPassRate);
            double stdDevEquipmentAutomationLevel = ComputeUtils.calculateStandardDeviation(normalizedEquipmentAutomationLevel);
            double stdDevMonthlyCapacity = ComputeUtils.calculateStandardDeviation(normalizedMonthlyCapacity);
            double stdDevMaxCapacity = ComputeUtils.calculateStandardDeviation(normalizedMaxCapacity);
            double stdDevEquipmentFailureRate = ComputeUtils.calculateStandardDeviation(normalizedEquipmentFailureRate);
            double stdDevQualityCertificateCount = ComputeUtils.calculateStandardDeviation(normalizedQualityCertificateCount);
            double stdDevPatentCount = ComputeUtils.calculateStandardDeviation(normalizedPatentCount);

            // 计算总标准差
            double totalStdDev = stdDevAverageProductionCycle + stdDevQualityCheckPassRate + stdDevEquipmentAutomationLevel + stdDevMonthlyCapacity +
                    stdDevMaxCapacity + stdDevEquipmentFailureRate + stdDevQualityCertificateCount + stdDevPatentCount;

            // 计算权重
            double weightAverageProductionCycle = (totalStdDev == 0) ? 0.125 : stdDevAverageProductionCycle / totalStdDev;
            double weightQualityCheckPassRate = (totalStdDev == 0) ? 0.125 : stdDevQualityCheckPassRate / totalStdDev;
            double weightEquipmentAutomationLevel = (totalStdDev == 0) ? 0.125 : stdDevEquipmentAutomationLevel / totalStdDev;
            double weightMonthlyCapacity = (totalStdDev == 0) ? 0.125 : stdDevMonthlyCapacity / totalStdDev;
            double weightMaxCapacity = (totalStdDev == 0) ? 0.125 : stdDevMaxCapacity / totalStdDev;
            double weightEquipmentFailureRate = (totalStdDev == 0) ? 0.125 : stdDevEquipmentFailureRate / totalStdDev;
            double weightQualityCertificateCount = (totalStdDev == 0) ? 0.125 : stdDevQualityCertificateCount / totalStdDev;
            double weightPatentCount = (totalStdDev == 0) ? 0.125 : stdDevPatentCount / totalStdDev;

            // 计算分数
            for (int i = 0; i < group.size(); i++) {
                TechnologyAggInfo info = group.get(i);

                double score = (normalizedAverageProductionCycle.get(i) * weightAverageProductionCycle) +
                        (normalizedQualityCheckPassRate.get(i) * weightQualityCheckPassRate) +
                        (normalizedEquipmentAutomationLevel.get(i) * weightEquipmentAutomationLevel) +
                        (normalizedMonthlyCapacity.get(i) * weightMonthlyCapacity) +
                        (normalizedMaxCapacity.get(i) * weightMaxCapacity) +
                        (normalizedEquipmentFailureRate.get(i) * weightEquipmentFailureRate) +
                        (normalizedQualityCertificateCount.get(i) * weightQualityCertificateCount) +
                        (normalizedPatentCount.get(i) * weightPatentCount);

                TechnologyScores technologyScore = new TechnologyScores();
                technologyScore.setChainType(info.getChainType());
                technologyScore.setEnterpriseName(info.getEnterpriseName());
                technologyScore.setScenario(info.getScenario());
                technologyScore.setProduct(info.getProduct());
                technologyScore.setEvent(info.getEvent());
                technologyScore.setScore(ComputeUtils.roundToTwoDecimalPlaces((float) score));

                scoresList.add(technologyScore);
            }
        }

        return scoresList;
    }
}
